﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Model;
using FairyGUI;
using UnityEngine;
using DG.Tweening;

namespace MDFGame
{
    public abstract class CardUIView
    {
        protected CardUIComponent Ccom;//外围组件引用
        protected DescribeUIView DView;
        public GComponent MainUI;//卡片UI组件本体
        public GLoader CardPic;//卡片图片装载器
        public Dictionary<CardUIText, GRichTextField> CardText;//卡片文本字段
        public Controller CardControl;//卡片控制器
        public GImage Light;//背景色
        protected Sequence Sequence;//动画队列

        private Color _LightTemp;

        /// <summary>
        /// 卡片UI创建函数
        /// 默认所有卡片UI轴心均为中间点
        /// </summary>
        /// <param name="UI">UI组件</param>
        /// <param name="picpath">UI图片路径</param>
        public void Create(GComponent UI, CardUIComponent ccom)
        {
            GlobalComponent _config = GameRoot.Scene.GetComponent<GlobalComponent>();
            Sequence = DOTween.Sequence();//初始化动画队列
            CardText = new Dictionary<CardUIText, GRichTextField>();//初始化卡片文本组件区域
            Ccom = ccom;//保存上级UIComponent引用
            DView = GameRoot.Scene.GetComponent<FieldInfoComponent>().DescribeUIView;
            MainUI = UI;//保存卡片UI引用
            if (_config.GameCardSizeX > 0 && _config.GameCardSizeY > 0)
            {
                MainUI.SetSize(_config.GameCardSizeX, _config.GameCardSizeY);//如果存在标准大小定义则设置，否则使用UI设计的卡片默认大小
            }
            MainUI.SetPivot(0.5f, 0.5f, true);//设置轴心为中心便于旋转卡片
            MainUI.SetXY(-MainUI.x,-MainUI.y);//设置卡片初始位置在场景外
            /*保存子组件引用*/
            CardPic = MainUI.GetChild("CardPic").asLoader;
            CardControl = MainUI.GetController("CC");
            Light = MainUI.GetChild("Effect").asImage;//指的是背景的选定光效颜色
            /*可点击可拖动*/
            MainUI.touchable = true;
            MainUI.draggable = true;

            LinkTextField();//不同类型卡片的卡片文字区域不同 需要各自绑定

            /*注册函数*/
            MainUI.onClick.Add(OnClick);

            MainUI.onRollOver.Add(OnRollIn);
            MainUI.onRollOut.Add(OnRollOut);

            MainUI.onDragStart.Add(DragStart);
            MainUI.onDragMove.Add(DragMove);
            MainUI.onDragEnd.Add(DragEnd);

            Sequence.OnStepComplete(MoveFinish);

            ChangePic();
            /*创建不会立即显示*/
            MainUI.visible = false;

        }

        protected abstract void LinkTextField();
        /// <summary>
        /// 卡片入场，此时才会正式显示卡片
        /// </summary>
        /// <param name="location">卡片入场的初始所属区域</param>
        public void Enter(GComponent location = null)
        {
            if (location != null)
            {
                MainUI.SetXY(location.x, location.y);
                MainUI.RemoveFromParent();//由原父组件离开
                location.AddChild(MainUI);//加入到所属区域父组件
            }
            MainUI.visible = true;
        }
        //卡片离场
        public void Leave()
        {
            /*不可视+卡片离开场外，但依旧会挂载在其父组件下*/
            MainUI.visible = false;
            MainUI.SetXY(-MainUI.x,-MainUI.y);
        }
       

        //玩家焦点悬浮
        protected void OnRollIn()
        {
            //如果没有拖动，那么执行悬浮
            if (!MainUI.dragging)
            {
                //卡片放大到1.3倍
                MainUI.scaleX = 1.3f;
                MainUI.scaleY = 1.3f;
            }
            //悬停的时候玩家已经关注选择了这张卡
            Watching();
        }
        protected void OnRollOut()
        {
            DeWatching();
            MainUI.scaleX = 1f;
            MainUI.scaleY = 1f;
        }

        //拖动
        protected void DragStart()
        {
            if (Ccom.CanDrag)
            {
                MainUI.touchable = false;//依旧可以拖动，但是此时拖动过程中卡片下方区域将会收到悬停消息
                MainUI.scaleX = 0.5f;
                MainUI.scaleY = 0.5f;//拖动中大小变一半便于看背景区域
                Ccom.cx = MainUI.x;//卡片拖动之前坐标，用于拖动终点无效情况回退原位置
                Ccom.cy = MainUI.y;
                DView.HideView();//拖动中不需要显示介绍框
            }
        }
        protected void DragMove()
        {
            MainUI.scaleX = 0.5f;
            MainUI.scaleY = 0.5f;//保持大小
        }
        protected void DragEnd()
        {
            /*用于释放卡牌时向目标区域发送消息*/
            GObject touch = GRoot.inst.touchTarget;
            while (touch != null)
            {
                if (touch.hasEventListeners("CardIn"))
                {
                    touch.RequestFocus();
                    touch.DispatchEvent("CardIn",Ccom.Parent);
                    MainUI.touchable = true;//记得设置回可触摸
                    OnRollIn();
                    return;
                }
                touch = touch.parent;
            }
            Log.Info("当前卡片移动终点无区域");
            MainUI.touchable = true;//记得设置回可触摸
            OnRollIn();
        }

        //点击【选择或切换状态】
        protected void OnClick()
        {
            //如果单位可以被点击选中
            if (Ccom.CanClick)
            {
                if (Ccom.CanTurn)
                {
                    TurnChangeCard();
                    return;
                }
                if (Ccom.Choosed)
                {
                    DeChoose();
                    return;
                }
                if (!Ccom.Choosed)
                {
                    Choose();
                    return;
                }
            }
        }
        //改变卡片图案
        public void ChangePic()
        {
            CardPic.texture = new NTexture(Ccom.CardTexture);
        }
        //根据外部状态强制更新UI可操作性
        public void UpdateState()
        {
            MainUI.draggable = Ccom.CanDrag;
            MainUI.touchable = Ccom.CanTurn;
            if (Ccom.CanClick)
            {
                //可选择的是黄色
                Light.color = Color.yellow;
            }
            else
            {
                //更新后不可点击，改为绿色
                Light.color = Color.green;
            }
        }

        /// <summary>
        /// 卡片移动到指定坐标
        /// </summary>
        /// <param name="target">目标坐标</param>
        /// <param name="time">缓动时间[默认1S]</param>
        public void MoveTo(Vector2 target,float time=1f)
        {
            //对于自动移动对象，阻止玩家进行操作干扰
            MainUI.draggable = false;
            MainUI.touchable = false;
            Sequence.Append(DOTween.To(
                () => MainUI.xy,//起始数值
                x=>MainUI.xy=x,//指定变量
                target,//目标数值
                time//动画用时
                ).SetEase(Ease.InOutQuad)//缓动方式
            );
        }
        /// <summary>
        /// 卡片横竖切换[默认1S]
        /// </summary>
        /// <param name="time"></param>
        public void TurnChangeCard(float time = 1f)
        {
            //对于自动移动对象，阻止玩家进行操作干扰
            MainUI.draggable = false;
            MainUI.touchable = false;
            //如果竖置状态，90度，横置，负90度
            float _rotation = ((Ccom.cardState & CardStateType.ERECTION) != 0) ? 90 : -90;
            Sequence.Insert(0, DOTween.To(
                () => MainUI.rotation,
                x => MainUI.rotation = x,
                _rotation,
                time
                ).SetEase(Ease.Linear)
                .OnComplete(RotateFinish));
        }
        /// <summary>
        /// 卡片正反面切换
        /// </summary>
        public void TapChangeCard()
        {
            //正切反
            if (CardControl.selectedIndex == 0 || CardControl.selectedIndex == 2)
            {
                CardControl.selectedIndex++;
                Ccom.cardState = Ccom.cardState ^ CardStateType.UP | CardStateType.DOWN;
            }
            //反切正
            else
            {
                CardControl.selectedIndex--;
                Ccom.cardState = Ccom.cardState ^ CardStateType.DOWN | CardStateType.UP;
            }
        }

        protected virtual void MoveFinish()
        {
                MainUI.draggable = true;
                MainUI.touchable = true;
        }

        protected virtual void RotateFinish()
        {
            //竖切横
            if ((Ccom.cardState & CardStateType.ERECTION) != 0)
            {
                Ccom.cardState = Ccom.cardState ^ CardStateType.ERECTION | CardStateType.TRANSVERSE;
            }
            //横切正
            else
            {
                Ccom.cardState = Ccom.cardState ^ CardStateType.TRANSVERSE | CardStateType.ERECTION;
            }
        }

        //移动/悬停选择【绿色】
        public void Watching()
        {
            //如果之前不是关注状态
            if (!Ccom.Watching)
            {
                Ccom.Watching = true;//设置状态为关注中
                CardControl.selectedIndex += 2;//设置卡片状态为关注状态
                _LightTemp = Light.color;//临时保存当前卡片背景光颜色
                Light.color = Color.green;//设置为绿色
                DView.MoveView(MainUI);//设置详细文本介绍框位置
                DView.ShowView(Ccom.Parent.GetComponent<CardInfoComponent>().CardDescribe);//设置文本并显示
                return;
            }
            //非拖动状态，说明拖动结束了
            if (!MainUI.dragging)
            {
                //如果是关注状态重复调用没有必要每次都设置文本，但因为拖动结束之后还会再执行一次所以为了刷新位置还是要再来一轮
                DView.MoveView(MainUI);
                DView.ShowView();//默认文本为null不会有任何变化，直接显示
            }
        }
        protected void DeWatching()
        {
            //只有当之前是关注中才会取消状态
            if (Ccom.Watching)
            {
                Ccom.Watching = false;
                CardControl.selectedIndex -= 2;
                Light.color = _LightTemp;//复原关注前的背景颜色
                DView.HideView();//隐藏介绍框
            }
        }

        //选择模式下已选定【红色】和可手动切换横竖状态
        public void Choose()
        {
            Ccom.Choosed = true;
            CardControl.selectedIndex += 2;
            Light.color = Color.red;
        }
        protected void DeChoose()
        {
            Ccom.Choosed = false;
            CardControl.selectedIndex -= 2;
            Light.color = Color.yellow;
        }
    }
}
